package cn.gov.pbc.gd.credit.log;


import java.lang.reflect.Field;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.liu.jbase.ResultVo;
import com.liu.jbase.annotation.LogAnnotation;
import com.liu.jbase.util.AnnotationUtil;
import com.liu.tools.DateUtil;
import com.liu.tools.NetHelper;
import com.liu.tools.PrimaryUtil;

import cn.gov.pbc.gd.credit.common.constant.CodeConstant;
import cn.gov.pbc.gd.credit.common.constant.CommonConstant;
import cn.gov.pbc.gd.credit.common.constant.LogConstant;
import cn.gov.pbc.gd.credit.common.model.UserModel;
import cn.gov.pbc.gd.credit.common.service.redis.IRedisService;
import cn.gov.pbc.gd.credit.common.util.UserUtil;
import cn.gov.pbc.gd.credit.common.vo.LoginVo;
import cn.gov.pbc.gd.credit.log.service.log.IMongoService;
import cn.gov.pbc.gd.credit.vo.inquiry.InquiryVo;
import cn.gov.pbc.gd.credit.vo.log.LogInquiryVo;
import cn.gov.pbc.gd.credit.vo.log.LogLoginVo;
import cn.gov.pbc.gd.credit.vo.log.LogOperateVo;

/**
 * @date 2017年5月4日
 * @time 下午3:35:31
 * @author liuxingmi
 * @desc 拦截器
 */
@Component
@Aspect
@Order(value = Ordered.HIGHEST_PRECEDENCE + 1000)
public class LogAspect {
	
	private static Logger logger = LoggerFactory.getLogger(LogAspect.class);
	
	@Autowired
	private IMongoService mongoService;
	
	@Autowired
	private IRedisService redisService;
	
	// 匹配  包下所有类的所有方法作为切入点  
    @Around("(execution(* cn.gov.pbc.gd.credit.*.service..*.impl..*Impl.*(..)) && @annotation(annotation)) && !execution(* cn.gov.pbc.gd.credit.common.service..*(..))")  
    public Object around(ProceedingJoinPoint jp, LogAnnotation annotation) throws java.lang.Throwable {  
        
    	String methodName = jp.getSignature().getName();
    	String methodPath = jp.getTarget().getClass() + ":" + methodName;
    	logger.debug("LogAspect:around msg=" + methodPath + "触发日志公用拦截器！");
       
   	    // 获取request
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String sid = request.getParameter("sid");
    	
        Object rvt = jp.proceed();
        if(rvt == null){
        	return new ResultVo<>();
        }
        ResultVo<?> resultDto = (ResultVo<?>) rvt;
        Object object = jp.getArgs()[0];
        
        UserModel userModel = UserUtil.getUserModel(sid, redisService);
        LoginVo vo = null;
        if("login".equals(methodName) && resultDto.getData() != null){
        	userModel = (UserModel) resultDto.getData();        	
        }
        
        Field field = AnnotationUtil.getInstance().getAnnotationPrimaryField(object.getClass());
        Object objId = null;
        if(field != null){
        	objId = field.getDeclaringClass().getDeclaredMethod("get" + StringUtils.capitalize(field.getName())).invoke(object);
        }
        String ip = NetHelper.getIpAddr(request);
        if(annotation != null){
        	
        	switch (annotation.logType()) {
			
        	case LogConstant.LOG_LOGIN:	
        		vo = new LoginVo();
            	if(object != null){
            		vo = (LoginVo) object;
            	}
        		LogLoginVo logVo = new LogLoginVo();
        		logVo.setId(PrimaryUtil.primaryId("L"));
				if(userModel != null){
					logVo.setCorpId(userModel.getCorpId());
					logVo.setUserId(userModel.getUserId());
					logVo.setDeptId(userModel.getDeptId());
					logVo.setAuthType(userModel.getAuthType());
					logVo.setSid(userModel.getSid());					
					logVo.setCorpName(userModel.getUserName());
				}
				
				logVo.setSimilar(vo.getSimilar());
				logVo.setAccount(vo.getAccount());
				logVo.setCreateMills(DateUtil.getCurrentFormatMill());
				logVo.setCreateTime(new Date());
				logVo.setLoginTime(new Date());
				logVo.setLoginIp(ip);
				if(CodeConstant.SUCCESS.equals(resultDto.getCode())){
					logVo.setLoginResult(1);
				} else {
					logVo.setLoginResult(0);
					logVo.setNote(resultDto.getMsg());
				}
				
				mongoService.addLogLogin(logVo, request);
        		
				break;
				
			case LogConstant.LOG_OPERATE:	
				
				LogOperateVo logOperateVo = new LogOperateVo();
				logOperateVo.setContent(annotation.content());
				logOperateVo.setId(PrimaryUtil.primaryId("L"));
				if(userModel != null){
					logOperateVo.setCorpId(userModel.getCorpId());
					logOperateVo.setOperatorId(userModel.getUserId());
					logOperateVo.setDeptId(userModel.getDeptId());
					logOperateVo.setSid(sid);	
					logOperateVo.setCorpName(userModel.getUserName());
					logOperateVo.setAccount(userModel.getAccount());
				}
				logOperateVo.setCreateMills(DateUtil.getCurrentFormatMill());
				logOperateVo.setCreateTime(new Date());
				logOperateVo.setOperateTable(annotation.moduleName());
				logOperateVo.setOperateType(LogConstant.ADD);
				logOperateVo.setOperateIp(NetHelper.getIpAddr(request));
				logOperateVo.setComeFrom(1);
				if (objId != null) {
					logOperateVo.setSourceId(objId.toString());
				}
				if(CodeConstant.SUCCESS.equals(resultDto.getCode())){
					logOperateVo.setOperateResult(1);
				} else {
					logOperateVo.setOperateResult(0);
					logOperateVo.setNote(resultDto.getMsg());
				}
				
				mongoService.addLogOperate(logOperateVo, request);
				break;
			
			case LogConstant.LOG_QUERY:		
				
				InquiryVo inquiryVo =JSON.parseObject(JSON.toJSONString(object), InquiryVo.class);
				
				LogInquiryVo logInquiryVo = new LogInquiryVo();
				logInquiryVo.setId(PrimaryUtil.primaryId("L"));
				if(userModel != null){
					logInquiryVo.setCorpId(userModel.getCorpId());
					logInquiryVo.setOperatorId(userModel.getUserId());
					logInquiryVo.setDeptId(userModel.getDeptId());
					logInquiryVo.setSid(sid);	
					logInquiryVo.setAccount(userModel.getAccount());
				}
				
				logInquiryVo.setSimilar(inquiryVo.getSimilar());
				logInquiryVo.setCreateMills(DateUtil.getCurrentFormatMill());
				logInquiryVo.setCreateTime(new Date());
				logInquiryVo.setIp(ip);
				logInquiryVo.setComeFrom(1);
				logInquiryVo.setCardNum(inquiryVo.getCardNum());
				logInquiryVo.setUserName(inquiryVo.getUserName());
				logInquiryVo.setQueryResult("0");
				if (objId != null) {
					logInquiryVo.setInquiryId(objId.toString());
				}
				
				if(annotation.option().equals(LogConstant.PERSON_QUERY)){
					logInquiryVo.setInquiryType(CommonConstant.INQUIRY_TYPE_PERSON);
				}
				
				if(annotation.option().equals(LogConstant.AGENT_QUERY)){
					logInquiryVo.setInquiryType(CommonConstant.INQUIRY_TYPE_AGENT);
				}
				
				if(annotation.option().equals(LogConstant.JUSTICE_QUERY)){
					logInquiryVo.setInquiryType(CommonConstant.INQUIRY_TYPE_JUSTICE);
				}
				mongoService.addLogInquiry(logInquiryVo, request);
				break;

			default:
				break;
			}
        }
        
        return resultDto;  
    } 
        
}
